<template>
  <div v-if="uploadStatus">
    <!-- 浮动按钮 -->
    <div
      v-show="!showModal"
      class="float-button"
      @click="showModal = true"
    >
      <img :src="upIcon" />
      <span>视频上传成功 ({{ successNum }}/{{ fileList.length }})</span>
    </div>

    <!-- 上传弹窗 -->
    <a-modal
      v-model:visible="showModal"
      :width="800"
      title="上传视频"
      :mask-closable="false"
      :footer="null"
      @cancel="closeWin"
    >
      <a-row :gutter="[0,10]">
        <a-col :span="24">
          <a-upload-dragger
            :multiple="true"
            :before-upload="beforeUpload"
            :file-list="[]"
          >
            <p class="ant-upload-drag-icon">
              <InboxOutlined />
            </p>
            <p class="ant-upload-text">请将视频拖拽到此处上传</p>
            <p class="ant-upload-hint">支持一次上传多个 / 支持2G以内的mp4文件</p>
          </a-upload-dragger>
        </a-col>

        <a-col :span="24">
          <a-table
            :columns="columns"
            :data-source="fileList"
            :pagination="false"
            row-key="id"
          />
        </a-col>

        <a-col :span="24">
          <div class="r-r-flex">
            <a-button type="primary" @click="closeWin">完成</a-button>
            <a-button type="default" class="mr-16" @click="showModal = false">
              最小化
            </a-button>
          </div>
        </a-col>
      </a-row>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { ref, h, watch } from "vue";
import { useUserStore } from "@/store";
import { InboxOutlined } from "@ant-design/icons-vue";
import {
  message,
  Modal as AModal,
  Upload as AUpload,
  Button as AButton,
  Row as ARow,
  Col as ACol,
  Table as ATable,
  Progress as AProgress,
  Tag as ATag,
} from "ant-design-vue";

import { generateUUID, parseVideo } from "@/utils";
import { minioUploadId, minioMergeVideo } from "@/api/upload";
import { UploadChunk } from "@/js/minio-upload-chunk";

import upIcon from "@/assets/images/commen/upload.png";

interface FileItem {
  id: string;
  file: File;
  upload: {
    handler: any;
    progress: number;
    status: number;
    remark: string;
  };
  video: {
    duration: number;
    poster: string;
  };
}

const store = useUserStore();
const uploadStatus = ref(store.uploadStatus);
const categoryIds = ref(store.uploadCateIds);

const showModal = ref(false);
const localFileList = ref<FileItem[]>([]);
const fileList = ref<FileItem[]>([]);
const successNum = ref(0);

const intervalId = ref<number>();
const intervalId2 = ref<number>();

const columns = [
  {
    title: "视频",
    dataIndex: "name",
    key: "name",
    customRender: ({ record }: any) => record.file.name,
  },
  {
    title: "大小",
    dataIndex: "size",
    key: "size",
    customRender: ({ record }: any) =>
      `${(record.file.size / 1024 / 1024).toFixed(2)}M`,
  },
  {
    title: "进度",
    dataIndex: "progress",
    key: "progress",
    customRender: ({ record }: any) =>
      record.upload.status === 0
        ? "等待上传"
        : h(AProgress, { percent: record.upload.progress, size: "small", steps: 20 }),
  },
  {
    title: "操作",
    key: "action",
    customRender: ({ record }: any) => {
      return h(
        "div",
        {},
        [
          record.upload.status === 5
            ? h(
                AButton,
                {
                  type: "link",
                  size: "small",
                  class: "c-red",
                  onClick: () => record.upload.handler.retry(),
                },
                "失败.重试"
              )
            : null,
          record.upload.status === 7 ? h(ATag, { color: "success" }, "上传成功") : null,
        ]
      );
    },
  },
];

const getMinioUploadId = async () => {
  let resp: any = await minioUploadId("mp4");
  return resp.data;
};

watch(
  () => store.uploadStatus,
  (val) => {
    uploadStatus.value = val;
    if (val) {
      showModal.value = true;
      intervalId.value = window.setInterval(() => {
        successNum.value = localFileList.value.filter((it) => it.upload.status === 7).length;
      }, 5000);
      intervalId2.value = window.setInterval(() => {
        const div = document.createElement("div");
        document.body.appendChild(div);
        div.click();
      }, 10000);
    } else {
      clearInterval(intervalId.value);
      clearInterval(intervalId2.value);
    }
  }
);

const beforeUpload = async (file: File, fileListParam: File[]) => {
  if (file.size > 2 * 1024 * 1024 * 1024) {
    message.error(`${file.name} 大小超过2G`);
    return AUpload.LIST_IGNORE;
  }
  if (fileListParam.length > 10) {
    message.config({ maxCount: 1 });
    message.error("单次最多上传10个视频");
    return AUpload.LIST_IGNORE;
  } else {
    message.config({ maxCount: 10 });
  }

  if (file.type === "video/mp4") {
    const videoInfo = await parseVideo(file);
    const data = await getMinioUploadId();
    const run = new UploadChunk(file, data["upload_id"], data["filename"]);
    const item: FileItem = {
      id: generateUUID(),
      file,
      upload: { handler: run, progress: 0, status: 0, remark: "" },
      video: { duration: videoInfo.duration, poster: videoInfo.poster },
    };

    run.on("success", () => {
      minioMergeVideo(
        data["filename"],
        data["upload_id"],
        categoryIds.value.join(","),
        item.file.name,
        "mp4",
        item.file.size,
        item.video?.duration || 0,
        item.video?.poster || ""
      ).then(() => {
        item.upload.progress = 100;
        item.upload.status = run.getUploadStatus();
        fileList.value = [...localFileList.value];
      });
    });

    run.on("progress", (p: number) => {
      item.upload.status = run.getUploadStatus();
      item.upload.progress = p >= 100 ? 99 : p;
      fileList.value = [...localFileList.value];
    });

    run.on("error", (msg: string) => {
      item.upload.status = run.getUploadStatus();
      item.upload.remark = msg;
      fileList.value = [...localFileList.value];
    });

    run.start();
    localFileList.value.push(item);
    fileList.value = [...localFileList.value];
  } else {
    message.error(`${file.name} 并不是 mp4 视频文件`);
  }

  return AUpload.LIST_IGNORE;
};

const closeWin = () => {
  fileList.value.forEach((item) => {
    if (item.upload.status !== 5 && item.upload.status !== 7) {
      item.upload.handler.cancel();
    }
  });
  localFileList.value = [];
  fileList.value = [];
  successNum.value = 0;
  showModal.value = false;

  store.uploadAction({
    uploadStatus: false,
    uploadCateIds: [],
  })
};
</script>

<style scoped>
.float-button {
  width: auto;
  height: 32px;
  background: #ffffff;
  box-shadow: 0px 0px 16px 0px rgba(0, 0, 0, 0.1);
  border-radius: 16px;
  box-sizing: border-box;
  padding: 6px 8px;
  display: flex;
  align-items: center;
  position: fixed;
  right: 24px;
  bottom: 20px;
  z-index: 50;
  cursor: pointer;
  img {
    width: 20px;
    height: 20px;
  }
  span {
    margin-left: 6px;
    font-size: 12px;
    font-weight: 400;
    color: #ff4d4f;
  }
}

</style>
